﻿using System;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using System.Windows.Media;
using Styx;
using Styx.Common;
using Styx.CommonBot.Routines;
using Styx.TreeSharp;

namespace Loader
{
    public class DemonicLoader : CombatRoutine
    {
        private CombatRoutine CC;


        private string Data = @"<configuration>
   <runtime>
   <loadFromRemoteSources enabled=""true""/>
      <assemblyBinding xmlns=""urn:schemas-microsoft-com:asm.v1"">
         <dependentAssembly>
            <assemblyIdentity name=""Honorbuddy""
                              publicKeyToken=""50a565ab5c01ae50""
                              culture=""neutral"" />
            <bindingRedirect oldVersion=""$VER1$"" newVersion=""$VER2$""/>
         </dependentAssembly>
      </assemblyBinding>
   </runtime>
</configuration>
";


        private readonly String[] Keep = new[] { "DemonicLoader.cs", "Demonic.dll", "Demonic.pdb", "Settings", "Changelog.txt", "Scheduled.txt" };

        public DemonicLoader()
        {
            string settingsDirectory = Path.Combine(Utilities.AssemblyDirectory, "Routines\\Demonic");

            string path = settingsDirectory + @"\Demonic.dll";

            if (!File.Exists(path))
            {
                MessageBox.Show("Demonic not installed correctly! Ensure files look like;" + 
                            Environment.NewLine + 
                            Environment.NewLine +
                            "<Honorbuddy>/Routines/Demonic/Demonic.dll" + Environment.NewLine +
                            "<Honorbuddy>/Routines/Demonic/DemonicLoader.cs" + Environment.NewLine +
                            "<Honorbuddy>/Routines/Demonic/Settings/<XML Files>");
                return;
            }
            bool removed = false;
            var DInfo = new DirectoryInfo(settingsDirectory);
            foreach (FileInfo file in DInfo.GetFiles())
            {
                if (!Keep.Contains(file.Name))
                {
                    removed = true;
                    Logging.Write("Removing " + file.Name + " from Demonic directory");
                    file.Delete();
                }
            }
            if (removed)
            {
                MessageBox.Show("Removed unnecessary files from Demonic directory, if Demonic fails to work please restart honorbuddy.");
            }

            try
            {
                Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");


                string WantedVersion = "";
                byte[] Bytes = File.ReadAllBytes(path);

                Assembly asm = Assembly.Load(Bytes);
                //Assembly asm = Assembly.LoadFrom(path);


                foreach (AssemblyName t in asm.GetReferencedAssemblies().Where(t => t.Name == "Honorbuddy"))
                {
                    WantedVersion = t.Version.ToString();

                    break;
                }

                //Lets verify stuff
                string CurentVersion = Assembly.GetEntryAssembly().GetName().Version.ToString();

                //Only if needed

                string txt;
                try
                {
                    txt = File.ReadAllText(Path.Combine(Utilities.AssemblyDirectory, "Honorbuddy.exe.config"));
                }
                catch (Exception)
                {
                    txt = "";
                }

                //  Logging.Write(Colors.Green, txt);

                if (!txt.Contains(CurentVersion) || !txt.Contains(WantedVersion))
                {
                    string newStr = Data.Replace("$VER2$", CurentVersion);
                    newStr = newStr.Replace("$VER1$", WantedVersion);

                    //  Logging.Write(Colors.Blue, newStr);

                    File.WriteAllText(Path.Combine(Utilities.AssemblyDirectory, "Honorbuddy.exe.config"), newStr);
                    MessageBox.Show("Config file has been rewritten. Please restart honorbuddy.");
                    return;
                }

                foreach (Type t in asm.GetTypes())
                {
                    if (t.IsSubclassOf(typeof(CombatRoutine)) && t.IsClass)
                    {
                        object obj = Activator.CreateInstance(t);
                        CC = (CombatRoutine)obj;
                    }
                }
            }
            catch (ThreadAbortException)
            {
                throw;
            }
            catch (ReflectionTypeLoadException ex)
            {
                var sb = new StringBuilder();
                foreach (Exception exSub in ex.LoaderExceptions)
                {
                    sb.AppendLine(exSub.Message);
                    if (exSub is FileNotFoundException)
                    {
                        var exFileNotFound = exSub as FileNotFoundException;
                        if (!string.IsNullOrEmpty(exFileNotFound.FusionLog))
                        {
                            sb.AppendLine("Fusion Log:");
                            sb.AppendLine(exFileNotFound.FusionLog);
                        }
                    }
                    sb.AppendLine();
                }
                string errorMessage = sb.ToString();
                //Display or log the error based on your application.
                Logging.Write(errorMessage);
            }
            catch (Exception e)
            {
                Logging.Write(Colors.DarkRed, "An error occured while loading Demonic!");
                Logging.Write(e.ToString());
            }
        }

        #region Overrides of CombatRoutine

        public override string Name
        {
            get
            {
                return CC.Name;
            }
        }

        public override void Initialize()
        {
            CC.Initialize();
        }

        public override Composite CombatBehavior
        {
            get { return CC.CombatBehavior; }
        }

        public override Composite PreCombatBuffBehavior
        {
            get { return CC.PreCombatBuffBehavior; }
        }

        public override Composite PullBehavior
        {
            get { return CC.PullBehavior; }
        }

        public override Composite RestBehavior
        {
            get { return CC.RestBehavior; }
        }

        public override WoWClass Class
        {
            get
            {
                return WoWClass.Warlock;
            }
        }

        public override void OnButtonPress()
        {
            CC.OnButtonPress();
        }

        public override void Pulse()
        {
            CC.Pulse();
        }

        public override bool WantButton
        {
            get { return true; }
        }

        #endregion
    }
}
